/*
  数组的实例方法：
      reduce常见的应用场景：
        1. 数组求和
        2. 根据数组得到一个对象
        3. 根据数组得到一个数组
      小结：
        1. 什么时候可以不用给初始值：纯数字求和、求积
        2. 什么时候必须给初始值：数组中放的是对象求和（汇总）

      4. 实现数组 reduce 方法的 原理
 */

/*
3. reduce的应用，解决实际需求：
1. 根据ASCII码数组 ['73', '32', '108', '111', '118', '101', '32', '121', '111', '117']，
   得到一个字符串
2. 对数组：[
  {
    name: '篮球',
    price: 198,
    num: 2
  }, {
    name: '球鞋',
    price: 1999,
    num: 1
  }, {
    name: '球衣',
    price: 99,
    num: 4
  }, {
    name: '护腕',
    price: 29,
    num: 10
  }
]，求总价格

3. 统计每个名字出现的次数：['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']

4. 根据数据：['北京', '上海', '北京', '深圳', '杭州', '上海', '北京']
    得到数组 [['北京', 3], ['上海', 2], ['深圳', 1], ['杭州', 1]]
    
5. 更多关于reduce的面试及应用,  B站 [技术痞瑞] get更多技能

*/

// 实现reduce方法的原理
Array.prototype._reduce = function (callback, initialValue) {
  // 1. 判断有没有传入initialValue
  const flag = typeof initialValue !== 'undefined'
  // 2. 决定起始下标
  let i = flag ? 0 : 1
  // 3. 决定acc的初始值
  let acc = flag ? initialValue : this[0]
  // 循环数组，起始下标需要根据有无 initialValue 决定
  for (; i < this.length; i++) {
    // 不断的迭代acc
    acc = callback(acc, this[i], i, this)
  }
  // 返回迭代/汇总的结果
  return acc
}

// 1.
const ascii = ['73', '32', '108', '111', '118', '101', '32', '121', '111', '117']
const str = ascii._reduce((acc, item) => acc + String.fromCharCode(item), '')
console.log(str)

// 2.
const products = [
  {
    name: '篮球',
    price: 198,
    num: 2
  }, {
    name: '球鞋',
    price: 1999,
    num: 1
  }, {
    name: '球衣',
    price: 99,
    num: 4
  }, {
    name: '护腕',
    price: 29,
    num: 10
  }
]

const totalPrice = products._reduce((acc, cur) => acc + cur.price * cur.num, 0)
console.log(totalPrice)

// 3.
const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
const result = names._reduce((acc, cur) => {
  // acc[cur] = acc[cur] ? acc[cur] + 1 : 1
  acc[cur] = ++acc[cur] || 1
  return acc
}, {})
console.log(result)

// 4. 
const cities = ['北京', '上海', '北京', '深圳', '杭州', '上海', '北京']
const ret = cities._reduce((acc, cur, index, arr) => {
  acc[cur] = ++acc[cur] || 1
  // if (index === arr.length - 1) {// 迭代到了最后一次，需要返回一个整体的二维数组结果
  //   return Object.entries(acc)
  // } else {// 不是最后一次，返回acc的累计的结果
  //   return acc
  // }
  // 等同于上方的代码
  return index === arr.length - 1 ? Object.entries(acc) : acc
}, {})

console.log(ret)
